<?php

//分页方法
function page()
{
    $page = $_REQUEST['page'];
    $pagecount = $_REQUEST['pagecount'];
    if ($page == null || $page <= 0) {
        $page = 0;
    }
    if ($pagecount == null || $pagecount <= 0) {
        $pagecount = 20;
    }
    $startcount = $page * $pagecount;
    return $startcount . ',' . $pagecount;
}

function format_distance($distance)
{
    $dis = (int)$distance;
    if ($dis > 1000000) {
        $dis = round($dis / 1000000, 1);
        $dis = $dis * 10 . "km";
    } else if ($dis > 1000) {
        $dis = round($dis / 1000, 1);
        $dis = $dis . "km";
    } else {
        $dis = $dis / 1000 . "km";
    }

    return $dis;
}

//邀请码生成
function code()
{
    $len = 6;
    $chars = "ABCDEFGHIJKLMNPQRSTUVWXYZ123456789";
    mt_srand(10000000 * (double)microtime());
    for ($i = 0, $str = '', $lc = strlen($chars) - 1; $i < $len; $i++) {
        $str .= $chars[mt_rand(0, $lc)];
    }
    return $str;
}

function timestr($name)
{
    $time = strtotime($name);
    if (!$time) {
        $time = null;
        return $time;
    }
    $diff = time() - $time;
    if ($diff < 5) {
        $time = "刚刚";
    } else if ($diff < 60) {
        $time = $diff . "秒前";
    } else if ($diff < 3600) {
        $time = floor($diff / 60) . "分钟前";
    } else if ($diff < 86400) {
        $time = floor($diff / 3600) . "小时前";
    } else if ($diff < (86400 * 7)) {
        $time = floor($diff / 86400) . "天前";
    } else if ($diff < (86400 * 30)) {
        $time = floor($diff / 86400 / 7) . "周前";
    } else if ($diff < (86400 * 366)) {
        $time = floor($diff / 86400 / 30) . "个月前";
    } else if ($diff < (86400 * 366 * 3)) {
        $time = floor($diff / 86400 / 365) . "年前";
    } else {
        $time = date("Y-m-d H:i:s", $time);
    }
    return $time;
}

function distance($latitude, $longitude, $alias='')
{
    if ($alias) {
        $alias .='.';
    }

    $data = "case 
        when {$alias}xuni_discount = '0.0' then 
            ROUND(
                6378.138 * 2 * ASIN(
                    SQRT(
                        POW(
                            SIN(
                                (" . $latitude . " * PI() / 180 - {$alias}latitude * PI() / 180) / 2
                            ), 2
                        ) + COS (" . $latitude . " * PI() / 180) * COS({$alias}latitude * PI() / 180) * POW(
                            SIN(
                                (" . $longitude . " * PI() / 180 - {$alias}longitude * PI() / 180) / 2
                            ), 2
                        )
                    )
                ) * 1000
            ) 
        else 
            {$alias}xuni_discount END distance";

    return $data;
}

function changeTime($time) {
    if ($time >= 60) {
        $minute = floor($time / 60);

        $second = $time % 60;

        $minute = (int)$minute >= 10 ? $minute : '0' . $minute;
     } else {
        $minute = '00';
        $second = $time;
    }

    $second = (int)$second >= 10 ? $second : '0' . $second;

    return $minute . ':' . $second;
}

//实体转字符,并且全路径 转 相对路径，存数据库时
function in_content($content)
{
    if ($content) {
        $content = htmlspecialchars_decode(html_entity_decode($content), ENT_QUOTES);//把 HTML 实体转换为字符

        preg_match_all("/src=\"(.*?)\"/", $content, $img);

        foreach ($img[1] as $k => $v) {
            if (strpos($v, 'http') !== false || strpos($v, 'https') !== false) {
                if (is_https()) {
                    $prefix = 'https://';
                } else {
                    $prefix = 'http://';
                }
                // $_SERVER['HTTP_HOST'] 域名 ;SITE_PATH 自定义常量，入口文件所在目录路径
                $temp = str_replace($prefix . $_SERVER['HTTP_HOST'], '', $v);
                $content = str_replace($v, $temp, $content);
            }
        }
    }
    return $content;
}

//相对路径 转 全路径，从数据库取出时
function out_content($content)
{
    if ($content) {
        preg_match_all("/src=\"(.*?)\"/", $content, $img);
        preg_match_all("/poster=\"(.*?)\"/", $content, $img2);

        $img[1] = array_merge($img[1], $img2[1]);

        $img[1] = array_unique($img[1]);

        foreach ($img[1] as $k => $v) {
            if (strpos($v, 'http') === false && strpos($v, 'https') === false) {
                if (is_https()) {
                    $prefix = 'https://';
                } else {
                    $prefix = 'http://';
                }
                // $_SERVER['HTTP_HOST'] 域名 ;SITE_PATH 自定义常量，入口文件所在目录路径
                $content = str_replace($v, checkpath($prefix . $_SERVER['HTTP_HOST'] . '/' . $v), $content);
            }
        }
    }
    return $content;
}

// 访问来源是否是https
function is_https()
{
    if (!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off') {
        return TRUE;
    } else if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
        return TRUE;
    } else if (!empty($_SERVER['HTTP_FRONT_END_HTTPS']) && strtolower($_SERVER['HTTP_FRONT_END_HTTPS']) !== 'off') {
        return TRUE;
    }
    
    return FALSE;
}

function changeUrl($path = '', $local = 0)
{
    if ($path) {
        $oss = $local ? 0 : getenv('APP_OSS');

        if ($oss) {
            $path = 'https://' . getenv('OSS_BUCKET') . '.' . getenv('OSS_ENDPOINT') . $path;
        } else {
            $sith_path = str_replace('apis', '', substr($_SERVER['PHP_SELF'],0,stripos($_SERVER['PHP_SELF'],'index.php')-1));

            $prefix = is_https() ? 'https://' : 'http://';
            $prefix = strlen($sith_path) > 1 ? $prefix . $_SERVER['HTTP_HOST'] . $sith_path : $prefix . $_SERVER['HTTP_HOST'];

            if (is_array($path)) {
                foreach ($path as $key => $item) {
                    $path[$key] = checkpath($prefix . '/' . $item);
                }
            } else {
                $path = checkpath($prefix . '/' . $path);
            }
        }
    }
    
    return $path;
}

function checkpath($str)
{
    $str = str_replace('///', '/', $str);
    if (substr_count($str, '//') > 1) {
        $arr = explode('//', $str);
        $str = $arr[0] . '//' . $arr[1] . '/' . $arr[2];
    }
    return $str;
}

/*function chatTime($datetime)
{
    $start = strtotime(date('Ymd'));

    if (strtotime($datetime) >= ($start - (86400 * 14))) {
        $time = $datetime;
    } else if (strtotime($datetime) >= ($start - (86400 * 7))) {
        $time = '1周前';
    } else if (strtotime($datetime) >= ($start - 86400)) {
        $day = round((strtotime($datetime) - time()) / 86400);
        $time = $day . '天前';
    } else if (strtotime($datetime) > $start) {
        $time = '昨天 ' . date('H:i', strtotime($datetime));
    } else if (strtotime($datetime) > (time() - 3600)) {
        $time = '今天 ' . date('H:i', strtotime($datetime));
    } else if (strtotime($datetime) >= (time() - 60)) {
        $minute = round((strtotime($datetime) - time()) / 60);
        $time = $minute . '分钟前';
    } else {
        $minute = strtotime($datetime) - time();
        $time = $minute . '秒前';
    }

    return $time;
}*/

function fullPath($url): string
{
    return $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'] . str_replace('/index.php', '', str_replace('/apis', '', $_SERVER['SCRIPT_NAME'])) . '/' . $url;
}

function changefloor($floor)
{
    return floor(strval($floor * pow(10,2))) / pow(10,2);
}

function timeTodate($time, $lang = 'cn')
{
    if (!$time) {
        return '';
    }
    
    $current_time = $f_date = time();
    
    $d = $current_time - intval($time);
    $ld = $current_time - strtotime(date('Y-01-01')); //得出年
    $md = $current_time - strtotime('-1 month', strtotime(date('Y-m-d'))); //得出月
    $byd = $current_time - strtotime('-2 day', strtotime(date('Y-m-d'))); //前天
    $yd = $current_time - strtotime('-1 day', strtotime(date('Y-m-d'))); //昨天
    $wyd = $current_time - strtotime('-7 day', strtotime(date('Y-m-d'))); //7天
    
    $dd = $current_time - strtotime(date('Y-m-d')); //今天
    $td = $current_time - strtotime('1 day', strtotime(date('Y-m-d'))); //明天
    $atd = $current_time - strtotime('2 day', strtotime(date('Y-m-d'))); //后天
    
    
    $last_year = date('Y', strtotime('-1 month', strtotime(date('Y-m-d'))));
    
    if ($lang == 'cn') {
        if ($d <= 10) {
            $f_date = '刚刚';
        } else {
            switch ($d) {
                case $d < $td:
                    $f_date = '后天' . date('H:i', $time);
                    break;
                case $d < 0:
                    $f_date = '明天' . date('H:i', $time);
                    break;
                case $d < 60:
                    $f_date = $d . '秒前';
                    break;
                case $d < 3600:
                    $f_date = floor($d / 60) . '分钟前';
                    break;
                case $d <= $dd:
                    $f_date = date('H:i', $time);;
                    break;
                case $d < $yd:
                    $f_date = '昨天' . date('H:i', $time);
                    break;
                case $d < $byd:
                    $f_date = '前天' . date('H:i', $time);
                    break;
                case ($d < $wyd):
                    $f_date = floor(($current_time - $time)/86400) . '天前';
                    break;
                case ($d < $md && date('Y') == $last_year):
                    $f_date = date('m-d H:i', $time);
                    break;
                case $d < $ld:
                    $f_date = date('m-d', $time);
                    break;
                case $d < $atd:
                default:
                    $f_date = date('Y-m-d', $time);
                    break;
            }
        }
    } else {
        if ($d <= 10) {
            $f_date = 'just';
        } else {
            switch ($d) {
                case $d < $td:
                    $f_date = 'the day after tomorrow' . date('H:i', $time);
                    break;
                case $d < 0:
                    $f_date = 'tomorrow' . date('H:i', $time);
                    break;
                case $d < 60:
                    $f_date = $d . 'seconds ago';
                    break;
                case $d < 3600:
                    $f_date = floor($d / 60) . 'minutes ago';
                    break;
                case $d <= $dd:
                    $f_date = floor($d / 3600) . 'hour ago';
                    break;
                case $d < $yd:
                    $f_date = 'yesterday' . date('H:i', $time);
                    break;
                case $d < $byd:
                    $f_date = 'the day before yesterday' . date('H:i', $time);
                    break;
                case ($d < $md && date('Y') == $last_year):
                    $f_date = date('m-d H:i', $time);
                    break;
                case $d < $ld:
                    $f_date = date('m-d', $time);
                    break;
                case $d < $atd:
                default:
                    $f_date = date('Y-m-d', $time);
                    break;
            }
        }
    }
    return $f_date;
    
}
/**
 * 获取客户端IP地址（支持多层代理和IP验证）
 *
 * @param bool $validate 是否验证IP有效性（防止伪造）
 * @param bool $logInvalid 是否记录无效IP尝试
 * @return string|false 返回客户端IP地址，失败时返回false
 */
function getClientIP($validate = true, $logInvalid = true)
{
    $ip = null;
    $trustedProxies = [
        '192.168.1.0/24',  // 内部代理服务器网段
        '10.0.0.0/8',      // 私有IP网段示例（根据实际情况修改）
        '172.16.0.0/12'    // 私有IP网段示例（根据实际情况修改）
    ];

    // 按优先级从高到低检查可能的IP来源
    $headers = [
        'HTTP_X_FORWARDED_FOR',  // 经过代理服务器时，客户端真实IP会被记录在此
        'HTTP_CLIENT_IP',        // 客户端IP
        'HTTP_X_REAL_IP',        // Nginx代理时常用
        'HTTP_X_CLUSTER_CLIENT_IP', // 集群环境
        'HTTP_FORWARDED_FOR',    // RFC 7239标准
        'HTTP_FORWARDED',        // RFC 7239标准
        'REMOTE_ADDR'            // 最后一个与服务器直接连接的IP（可能是代理服务器）
    ];

    foreach ($headers as $header) {
        if (isset($_SERVER[$header])) {
            // 处理可能包含多个IP的情况（如：client,proxy1,proxy2）
            $ips = explode(',', $_SERVER[$header]);
            $ips = array_map('trim', $ips);

            // 从后向前遍历IP列表（最后一个IP通常是最近的代理服务器）
            for ($i = count($ips) - 1; $i >= 0; $i--) {
                $currentIP = $ips[$i];

                // 验证IP格式有效性
                if (filter_var($currentIP, FILTER_VALIDATE_IP,
                        FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6 |
                        FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) === false) {
                    if ($logInvalid) {
                        error_log("Invalid IP format: $currentIP from header $header");
                    }
                    continue;
                }

                // 如果启用验证，检查是否来自可信代理
                if ($validate) {
                    $isTrustedProxy = false;
                    foreach ($trustedProxies as $proxy) {
                        if (isIPInRange($currentIP, $proxy)) {
                            $isTrustedProxy = true;
                            break;
                        }
                    }

                    // 如果当前IP是可信代理，继续向前查找客户端IP
                    if ($isTrustedProxy) {
                        continue;
                    } else {
                        // 非可信代理，认为找到了真实客户端IP
                        $ip = $currentIP;
                        break 2;
                    }
                } else {
                    // 不验证时，直接返回第一个有效IP
                    $ip = $currentIP;
                    break 2;
                }
            }
        }
    }

    // 如果未找到有效IP，返回服务器直接连接的IP
    if (!$ip && isset($_SERVER['REMOTE_ADDR'])) {
        $ip = $_SERVER['REMOTE_ADDR'];
    }

    // 最终验证
    if ($ip && filter_var($ip, FILTER_VALIDATE_IP) === false) {
        if ($logInvalid) {
            error_log("Final IP validation failed: $ip");
        }
        return false;
    }

    return $ip ?: false;
}

/**
 * 检查IP是否在指定网段内
 *
 * @param string $ip 要检查的IP
 * @param string $range CIDR格式的网段（如：192.168.1.0/24）
 * @return bool 是否在网段内
 */
function isIPInRange($ip, $range)
{
    if (strpos($range, '/') === false) {
        return $ip === $range;
    }

    list($subnet, $mask) = explode('/', $range, 2);

    // IPv4处理
    if (strpos($ip, ':') === false) {
        $ip = ip2long($ip);
        $subnet = ip2long($subnet);
        $mask = ~((1 << (32 - $mask)) - 1);
        return ($ip & $mask) === ($subnet & $mask);
    }

    // IPv6处理（简化版，实际应用中建议使用gmp扩展）
    $ipParts = explode(':', $ip);
    $subnetParts = explode(':', $subnet);

    for ($i = 0; $i < min(count($ipParts), count($subnetParts)); $i++) {
        if ($ipParts[$i] !== $subnetParts[$i]) {
            return false;
        }
    }

    return true;
}





